package algorithm.dp;

import java.util.List;

public class 大礼包N {
    /*
     * 在LeetCode商店中， 有许多在售的物品。
     * 
     * 然而，也有一些大礼包，每个大礼包以优惠的价格捆绑销售一组物品。
     * 
     * 现给定每个物品的价格，每个大礼包包含物品的清单，以及待购物品清单。请输出确切完成待购清单的最低花费。
     * 
     * 每个大礼包的由一个数组中的一组数据描述，最后一个数字代表大礼包的价格，其他数字分别表示内含的其他种类物品的数量。
     * 
     * 任意大礼包可无限次购买。
     * 
     * 示例 1:
     * 
     * 输入: [2,5], [[3,0,5],[1,2,10]], [3,2] 输出: 14 解释: 有A和B两种物品，价格分别为¥2和¥5。
     * 大礼包1，你可以以¥5的价格购买3A和0B。 大礼包2， 你可以以¥10的价格购买1A和2B。 你需要购买3个A和2个B，
     * 所以你付了¥10购买了1A和2B（大礼包2），以及¥4购买2A。 示例 2:
     * 
     * 输入: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1] 输出: 11 解释:
     * A，B，C的价格分别为¥2，¥3，¥4. 你可以用¥4购买1A和2B，也可以用¥9购买2A，2B和1C。
     * 你需要买1A，2B和1C，所以你付了¥4买了1A和1B（大礼包1），以及¥3购买1B， ¥4购买1C。
     * 你不可以购买超出待购清单的物品，尽管购买大礼包2更加便宜。 说明:
     * 
     * 最多6种物品， 100种大礼包。 每种物品，你最多只需要购买6个。 你不可以购买超出待购清单的物品，即使更便宜。
     */
    public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) {
        /*
         * 1、购买大礼包后，物品不能超出 2、有可能你花了更少的钱买大礼包，但是由于要凑够数，所以你又需要花钱买零散物品导致总价飙升了
         */
        int[][][][][][] bag = new int[10][10][10][10][10][10];// 假设需要购买6种物品，对应索引表示该物品购买量,值表示最小花费
        int[] need = new int[6];
        int[] pri = new int[6];
        for (int i = 0; i < needs.size(); i++) {
            need[i] = needs.get(i);
            pri[i] = price.get(i);
        }
        for (int i1 = 0; i1 <= need[0]; i1++) {
            for (int i2 = 0; i2 <= need[1]; i2++) {
                for (int i3 = 0; i3 <= need[2]; i3++) {
                    for (int i4 = 0; i4 <= need[3]; i4++) {
                        for (int i5 = 0; i5 <= need[4]; i5++) {
                            for (int i6 = 0; i6 <= need[5]; i6++) {
                                bag[i1][i2][i3][i4][i5][i6] = i1 * pri[0] + i2 * pri[1] + i3 * pri[2] + i4 * pri[3]
                                        + i5 * pri[4] + i6 * pri[5];
                            }
                        }
                    }
                }
            }
        }
        for (List<Integer> bigBag : special) {
            int[] num = new int[6];
            int cost = bigBag.get(bigBag.size() - 1);
            for (int i = 0; i < bigBag.size() - 1; i++) {
                num[i] = bigBag.get(i);
            }
            for (int i1 = need[0]; i1 >= num[0]; i1--) {
                for (int i2 = need[1]; i2 >= num[1]; i2--) {
                    for (int i3 = need[2]; i3 >= num[2]; i3--) {
                        for (int i4 = need[3]; i4 >= num[3]; i4--) {
                            for (int i5 = need[4]; i5 >= num[4]; i5--) {
                                for (int i6 = need[5]; i6 >= num[5]; i6--) {
                                    int preCost = bag[i1][i2][i3][i4][i5][i6];
                                    int min = Math.min(preCost,
                                            bag[i1 - num[0]][i2 - num[1]][i3 - num[2]][i4 - num[3]][i5 - num[4]][i6
                                                    - num[5]] + cost);
                                    bag[i1][i2][i3][i4][i5][i6] = min;
                                }
                            }
                        }
                    }
                }
            }
        }
        return bag[need[0]][need[1]][need[2]][need[3]][need[4]][need[5]];
    }
}
